/*

* ------------------------------------------------------------------------
* ------------------------------------------------------------------------
* |     Smart-Shop开源商城系统/ Java商城-首选电商平台系统 请务必保留此注释头信息
* |     开源地址: https://gitee.com/ningbo-qishan/gruul-mall
* ------------------------------------------------------------------------
* ------------------------------------------------------------------------
* |     可正常分享和学习源码,未经授权 不可商用！
* |     商业版中台购买/开源版商业授权 联系技术客服
* |     官网:  https://www.73app.cn/
* ------------------------------------------------------------------------
* ------------------------------------------------------------------------
* |     Copyright (c) 2016-2999 宁波启山智软科技有限公司
* |     版权所有 ,侵权必究！
* ------------------------------------------------------------------------

*/
package com.medusa.gruul.gateway.filter;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.StrUtil;
import com.medusa.gruul.common.core.auth.model.CompleteUser;
import com.medusa.gruul.common.core.auth.model.constant.Headers;
import com.medusa.gruul.common.core.config.Jackson;
import com.medusa.gruul.common.core.constant.CommonConstants;
import com.medusa.gruul.common.core.util.Result;
import com.medusa.gruul.gateway.handler.FeignRequestHandler;
import com.medusa.gruul.gateway.feign.MultiClientAccountApi;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;


/**
 * 解析token数据添加到请求头
 *
 * @author 张治保
 * date 2021/12/9
 */
@Slf4j
@Component
@Order(Ordered.HIGHEST_PRECEDENCE + 1)
@RequiredArgsConstructor
public class MultiClientAccountAuthFilter implements GlobalFilter {

    private final MultiClientAccountApi multiClientAccountApi;

    @Override
    @SuppressWarnings("BlockingMethodInNonBlockingContext")
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        HttpHeaders headers = exchange.getRequest().getHeaders();
        String token = headers.getFirst(Headers.TOKEN);
        if (StrUtil.isBlank(token)) {
            return chain.filter(exchange);
        }
        FeignRequestHandler.set(token, headers.getFirst(CommonConstants.VERSION), headers.getFirst(Headers.PLATFORM));
        Result<CompleteUser> result = multiClientAccountApi.getUser();
        FeignRequestHandler.clear();
        log.info("解析token数据:{}", result);
        if (!result.isSuccess()) {
            ServerHttpResponse response = exchange.getResponse();
            response.setStatusCode(HttpStatus.OK);
            response.getHeaders().add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE);
            return response.writeWith(
                    Mono.just(
                            response.bufferFactory().wrap(Jackson.writeValueAsString(result).getBytes(StandardCharsets.UTF_8))
                    )
            );
        }
        CompleteUser completeUser = result.getData();

        ServerHttpRequest request = exchange.getRequest()
                .mutate()
                .header(Headers.USER, Base64.encodeUrlSafe(completeUser.getUserStr()))
                .header(Headers.JTI, completeUser.getJti())
                .build();
        return chain.filter(exchange.mutate().request(request).build());
    }
}
